/*
 * Copyright 2017 Baiyyy
 * @(#)PDFReport.java
 */

package com.byyy.ccts.core.utils.pdf;

import com.byyy.ccts.core.utils.DateUtils;
import com.byyy.ccts.core.utils.pdf.annotation.PDFColumn;
import com.byyy.ccts.core.utils.pdf.annotation.PDFTitle;
import com.byyy.ccts.core.utils.pdf.exception.PDFException;
import com.byyy.ccts.modules.cc.entity.ccts.TSHumiture;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.sql.Timestamp;
import java.util.*;
import java.util.List;

/**
 * Created by DELL on 2018-8-9.
 */
public class PDFReport {

    private static BaseFont bfChinese = null;
    private static Font subBoldFontChinese = null;
    private static Font subtitleChinese = null;
    private static Font titleChinese = null;

    static {
        // itext在pdf中输入中文字体(中文楷体)时：
        try {
            bfChinese = BaseFont.createFont("C:/WINDOWS/Fonts/SIMSUN.TTC,1", BaseFont.IDENTITY_H,
                    BaseFont.NOT_EMBEDDED);
            subBoldFontChinese = new Font(bfChinese, 8, Font.NORMAL);
            subtitleChinese = new Font(bfChinese, 10, Font.BOLD); // 模板抬头的字体
            titleChinese = new Font(bfChinese, 15, Font.BOLD); // 模板抬头的字体
        } catch (DocumentException e) {
            throw new PDFException(e);
        } catch (IOException e) {
            throw new PDFException(e);
        }
    }

    /**
     * 通用PDF导出
     * @param data
     * @param clz
     */
    public static void exportPDF(OutputStream os, List<?> data, Class<?> clz) {
        Document document = null;
        Paragraph title = null;

        try {
            // 设置之纸张为A4纸，左右上下边距全部为5，
            document = new Document(PageSize.A4, 50, 50, 50, 50);
            // 构造好的pdf文件输出位置
            PdfWriter.getInstance(document, os);
            document.open();

            // 设置标题
            PDFTitle pdfTitle = clz.getAnnotation(PDFTitle.class);
            // 抬头
            title = new Paragraph(pdfTitle.value(), titleChinese);
            // 居中设置
            title.setAlignment(Element.ALIGN_CENTER);
            // 设置行间距,设置上面空白宽度
            title.setLeading(10f);
            title.setSpacingAfter(15);
            document.add(title);

            // 获取PDF列属性
            List<PDFExportEntity> entities = generateExportEntity(clz);
            sortEntities(entities);
            // 生成头部信息
            createPDFRowTitle(document, entities);
            // 生成数据信息
            createPDFRow(document, data, entities);

        }
        catch (Exception e) {
            throw new PDFException(e);
        }
        finally {
            document.close();
        }
    }

    /**
     * 生成PDF头部信息
     * @param document
     * @param entities
     */
    private static void createPDFRowTitle(Document document, List<PDFExportEntity> entities) {
        try {
            PdfPTable pdfPTable = null;
            PdfPCell cell = null;
            pdfPTable = new PdfPTable(entities.size());
            pdfPTable.getDefaultCell().setBorder(0);
            pdfPTable.setLockedWidth(true);
            float[] totalWidth = new float[entities.size()];
            for (int i = 0; i < entities.size(); i++) {
                totalWidth[i] = entities.get(i).getWidth();
            }
                pdfPTable.setTotalWidth(totalWidth);
            for (int i = 0; i < entities.size(); i++) {
                cell = new PdfPCell(new Paragraph(entities.get(i).getName(), subtitleChinese));
                cell.setHorizontalAlignment(Element.ALIGN_CENTER);
                pdfPTable.addCell(cell);
            }
            document.add(pdfPTable);
        } catch (DocumentException e) {
            throw new PDFException(e);
        }
    }

    /**
     * 生成PDF数据信息
     * @param document
     * @param entities
     */
    private static void createPDFRow(Document document, List<?> data, List<PDFExportEntity> entities) {
        try {
            PdfPTable pdfPTable = null;
            PdfPCell cell = null;
            Object obj = null;
            Object value = null;

            pdfPTable = new PdfPTable(entities.size());
            pdfPTable.getDefaultCell().setBorder(1);
            pdfPTable.setLockedWidth(true);
            float[] totalWidth = new float[entities.size()];
            for (int i = 0; i < entities.size(); i++) {
                totalWidth[i] = entities.get(i).getWidth();
            }
            pdfPTable.setTotalWidth(totalWidth);

            Iterator<?> it = data.iterator();
            while (it.hasNext()) {
                obj = it.next();
                for (int i = 0; i < entities.size(); i++) {
                    value = entities.get(i).getMethod().invoke(obj, new Object[]{});
                    cell = new PdfPCell(new Paragraph(getValue(value, entities.get(i)), subBoldFontChinese));
                    cell.setHorizontalAlignment(Element.ALIGN_CENTER);
                    pdfPTable.addCell(cell);
                }
            }
            document.add(pdfPTable);
        }
        catch (Exception e) {
            throw new PDFException(e);
        }
    }

    /**
     * 生成PDF导出列属性
     * @param clz
     * @return
     */
    private static List<PDFExportEntity> generateExportEntity(Class<?> clz)  {
        // 获取PDF列属性
        PDFColumn column = null;
        PDFExportEntity exportEntity = null;
        Field[] fields = clz.getDeclaredFields();
        List<PDFExportEntity> entities = new ArrayList<>();
        try {
            for (Field field : fields) {
                column = field.getAnnotation(PDFColumn.class);
                if (column != null) {
                    exportEntity = new PDFExportEntity();
                    exportEntity.setName(column.name());
                    exportEntity.setOrder(column.order());
                    exportEntity.setWidth(column.width());
                    exportEntity.setMethod(clz.getDeclaredMethod(getMethodName(field.getName())));
                    exportEntity.setFormat(column.format());
                    entities.add(exportEntity);
                }
            }
        }
        catch (Exception e) {
            throw new PDFException(e);
        }
        return entities;
    }

    /**
     * 将PDF导出列属性排序
     * @param exportEntities
     */
    private static void sortEntities(List<PDFExportEntity> exportEntities) {
        Collections.sort(exportEntities, new Comparator<PDFExportEntity>() {
            public int compare(PDFExportEntity column1, PDFExportEntity column2) {
                // order升序
                if (column1.getOrder() > column2.getOrder()) {
                    return 1;
                }
                if (column1.getOrder() == column2.getOrder()) {
                    return 0;
                }
                return -1;
            }
        });

    }

    /**
     * 获取属性的GET方法
     * @param fieldName
     * @return
     */
    private static String getMethodName(String fieldName) {
        StringBuilder sb = new StringBuilder("get");
        sb.append(fieldName.substring(0, 1).toUpperCase());
        sb.append(fieldName.substring(1, fieldName.length()));
        return sb.toString();
    }

    /**
     * 格式化值
     * @param value
     * @param entity
     * @return
     */
    private static String getValue(Object value, PDFExportEntity entity) {
        String ret = null;
        if (value instanceof String) {
            ret = (String) value;
        }
        else if (value instanceof Date) {
            ret = DateUtils.formatDate((Date) value, entity.getFormat());
        }
        else if (value instanceof Timestamp) {
            ret = DateUtils.formatDate((Timestamp) value, entity.getFormat());
        }
        else {
            ret = String.valueOf(value);
        }
        return ret;
    }

    public static void generateHumiturePDF(List<TSHumiture> list, OutputStream os) {
        Document document = null;
        BaseFont bfChinese = null;
        Paragraph title = null;
        String contextString = "";
        Font subBoldFontChinese = null;
        Font titleChinese = null;
        Font subtitleChinese = null;
        TSHumiture humiture = null;
        try {
            // itext在pdf中输入中文字体(中文楷体)时：
            bfChinese = BaseFont.createFont("C:/WINDOWS/Fonts/SIMSUN.TTC,1", BaseFont.IDENTITY_H,
                    BaseFont.NOT_EMBEDDED);
            subBoldFontChinese = new Font(bfChinese, 8, Font.NORMAL);
            subtitleChinese = new Font(bfChinese, 10, Font.BOLD); // 模板抬头的字体
            titleChinese = new Font(bfChinese, 15, Font.BOLD); // 模板抬头的字体
            // 设置之纸张为A4纸，左右上下边距全部为5，
            document = new Document(PageSize.A4, 50, 50, 50, 50);
            // 构造好的pdf文件输出位置
            PdfWriter.getInstance(document, os);

            document.open();
            title = new Paragraph("采集设备温度数据", titleChinese);// 抬头
            title.setAlignment(Element.ALIGN_CENTER); // 居中设置
            title.setLeading(10f);// 设置行间距//设置上面空白宽度
            document.add(title);

            PdfPTable pdfPTable = null;
            PdfPCell cell = null;
            pdfPTable = new PdfPTable(6);
            pdfPTable.setTotalWidth(new float[] { 60, 100, 50, 50, 50, 50 });
            cell = new PdfPCell(new Paragraph("", subtitleChinese));
            cell.setColspan(6);
            cell.setBorder(0);
            pdfPTable.addCell(cell);
            document.add(pdfPTable);

            pdfPTable = new PdfPTable(6);
            pdfPTable.getDefaultCell().setBorder(0);
            pdfPTable.setLockedWidth(true);
            pdfPTable.setTotalWidth(new float[]{ 60, 100, 50, 50, 50, 50});
            contextString = "设备编号";
            cell = new PdfPCell(new Paragraph(contextString, subtitleChinese));
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            pdfPTable.addCell(cell);
            contextString = "温度采集时间";
            cell = new PdfPCell(new Paragraph(contextString, subtitleChinese));
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            pdfPTable.addCell(cell);
            contextString = "温度值";
            cell = new PdfPCell(new Paragraph(contextString, subtitleChinese));
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            pdfPTable.addCell(cell);
            contextString = "信号量";
            cell = new PdfPCell(new Paragraph(contextString, subtitleChinese));
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            pdfPTable.addCell(cell);
            contextString = "电量";
            cell = new PdfPCell(new Paragraph(contextString, subtitleChinese));
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            pdfPTable.addCell(cell);
            contextString = "湿度值";
            cell = new PdfPCell(new Paragraph(contextString, subtitleChinese));
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            pdfPTable.addCell(cell);
            document.add(pdfPTable);

            pdfPTable = new PdfPTable(6);
            pdfPTable.getDefaultCell().setBorder(1);
            pdfPTable.setLockedWidth(true);
            pdfPTable.setTotalWidth(new float[]{ 60, 100, 50, 50, 50, 50});

            for (int i = 0; i < list.size(); i++) {
                humiture = list.get(i);
                cell = new PdfPCell(new Paragraph(humiture.getDeviceSn(), subBoldFontChinese));
                cell.setHorizontalAlignment(Element.ALIGN_CENTER);
                pdfPTable.addCell(cell);
                cell = new PdfPCell(new Paragraph(DateUtils.formatDate(humiture.getCollectTime(), "yyyy-MM-dd HH:mm:ss"), subBoldFontChinese));
                cell.setHorizontalAlignment(Element.ALIGN_CENTER);
                pdfPTable.addCell(cell);
                cell = new PdfPCell(new Paragraph(String.valueOf(humiture.getTemperature()), subBoldFontChinese));
                cell.setHorizontalAlignment(Element.ALIGN_CENTER);
                pdfPTable.addCell(cell);
                cell = new PdfPCell(new Paragraph(String.valueOf(humiture.getSemaphore()), subBoldFontChinese));
                cell.setHorizontalAlignment(Element.ALIGN_CENTER);
                pdfPTable.addCell(cell);
                cell = new PdfPCell(new Paragraph(String.valueOf(humiture.getElectric()), subBoldFontChinese));
                cell.setHorizontalAlignment(Element.ALIGN_CENTER);
                pdfPTable.addCell(cell);
                cell = new PdfPCell(new Paragraph(String.valueOf(humiture.getHumidity()), subBoldFontChinese));
                cell.setHorizontalAlignment(Element.ALIGN_CENTER);
                pdfPTable.addCell(cell);
            }
            document.add(pdfPTable);
        } catch (Exception e) {
            throw new PDFException(e);
        }
        finally {
            document.close();
        }
    }

    public static void main(String[] args) throws Exception {
        List<TSHumiture> humitures = new ArrayList<>();
        TSHumiture temp = new TSHumiture();
        temp.setDeviceSn("132456789");
        temp.setCollectTime(new Timestamp(new Date().getTime()));
        humitures.add(temp);
//        generateHumiturePDF(humitures, new FileOutputStream("D:\\test.pdf"));
        exportPDF(new FileOutputStream("D:\\test.pdf"), humitures, TSHumiture.class);
    }

}
